package com.hopital5.zhangyz

import freemarker.template.Configuration
import freemarker.template.Template
import org.junit.Before
import org.junit.Test
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider
import org.springframework.core.type.filter.AnnotationTypeFilter

import javax.persistence.Entity
import java.nio.file.Paths

/**
 * Created by zhangyz on 16-6-20.
 */
class GenerateSource {
    public static final String PACKAGE_NAME = GenerateSource.class.package.name
    public static final String PROJECT_DIR = Paths.get("").toAbsolutePath().toString()
    public static final String PACKAGE_NAME_DIR = PACKAGE_NAME.replace('.', '/')
    public static final String MAIN_DIR = '/src/main/java'
    public static final String TEST_DIR = '/src/test/groovy'
    def modelPath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/model/'
    def repositoryPath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/repository/'
    def servicePath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/service/'
    def controllerPath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/controller/'
    def controllerTestPath = PROJECT_DIR + TEST_DIR + '/' + PACKAGE_NAME_DIR + '/controller/'
    def voEnumPath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/vo/enums/'
    def voRequestPath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/vo/request/'
    def voResponsePath = PROJECT_DIR + MAIN_DIR + '/' + PACKAGE_NAME_DIR + '/vo/response/'
    private Configuration configuration

    @Before
    void init() {
        configuration = new Configuration()
        configuration.setClassForTemplateLoading(GenerateSource.class, "/source/template")
        ([modelPath, repositoryPath, servicePath, controllerPath, controllerTestPath, voEnumPath, voRequestPath, voResponsePath].collect({
            new File(it)
        }).findAll { !it.exists() }).each { it.mkdirs() }
    }

    @Test
    void repository() {
        getAllModelFiles().each { fileName ->
            def repositoryClass = new File(repositoryPath + fileName + 'Repository.java')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('repository', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    @Test
    void service() {
        getAllModelFiles().each { fileName ->
            def repositoryClass = new File(servicePath + fileName + 'Service.java')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('service', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    @Test
    void controller() {
        getAllModelFiles().each { fileName ->
            def repositoryClass = new File(controllerPath + fileName + 'Controller.java')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('controller', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    @Test
    void controllerTest() {
        getAllModelFiles().each { fileName ->

            def repositoryClass = new File(controllerTestPath + fileName + 'ControllerTest.groovy')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('controllerTest', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    @Test
    void voRequest() {
        getAllModelFiles().each { fileName ->
            def repositoryClass = new File(voRequestPath + fileName + 'VoRequest.java')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('voRequest', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    @Test
    void voResponse() {
        getAllModelFiles().each { fileName ->
            def repositoryClass = new File(voResponsePath + fileName + 'VoResponse.java')
            if (!repositoryClass.exists()) {
                repositoryClass.createNewFile()
                repositoryClass << getTemplate('voResponse', [packageName: PACKAGE_NAME, entityName: fileName])
            }
        }
    }

    private List<String> getAllModelFiles() {
        ClassPathScanningCandidateComponentProvider candidateComponentProvider = new ClassPathScanningCandidateComponentProvider(false)
        candidateComponentProvider.addIncludeFilter(new AnnotationTypeFilter(Entity.class))
        return candidateComponentProvider.findCandidateComponents(PACKAGE_NAME).collect {
            it.beanClassName.replaceAll(/^.*\./, '')
        }
    }

    private StringWriter getTemplate(String sourceTemplate, Map data) {
        Template template = configuration.getTemplate("${sourceTemplate}.ftl")
        def writer = new StringWriter()
        template.process(data, writer)
        return writer
    }
}
